﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Runtime.InteropServices;
using CNRegex.Enum;
using CNRegex.Dal;
using System.Linq.Expressions;
using System.Reflection;

namespace CNRegex.Web.Utility
{
	public class WebTools
	{

		public static string ScriptCloseDialog {
			get{
				return "<script>window.parent.closeDialog('refresh');</script>";
			}
		}

		/// <summary>
		/// 插入选项到selectlist中
		/// </summary>
		/// <param name="target"></param>
		/// <param name="text"></param>
		/// <param name="value"></param>
		/// <param name="selected"></param>
		/// <param name="location"></param>
		/// <returns></returns>
		public static IList<SelectListItem> InsertOption(SelectList target, string text, string value, [Optional, DefaultParameterValue(false)] bool selected, [Optional, DefaultParameterValue(EnumLoaction.First)] EnumLoaction location)
		{
			if (target == null)
				return null;
			SelectListItem item = new SelectListItem();
			item.Text = text;
			item.Value = value;
			item.Selected = selected;
			IList<SelectListItem> items = target.ToList();
			if (location == EnumLoaction.First)
				items.Insert(0, item);
			if (location == EnumLoaction.Last)
				items.Insert(items.Count - 1, item);
			return items;
		}

		public static bool IsNotExcuteAspx(string extension)
		{
			return
				extension.Equals(".css", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".js", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".jpg", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".gif", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".png", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".jpeg", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".ico", StringComparison.OrdinalIgnoreCase)
				|| extension.Equals(".swf", StringComparison.OrdinalIgnoreCase)
				;
		}

		public static int? ConvertNullableEnumToInt<T, U>(T enumValue)
		{
			if (enumValue == null)
				return null;
			return Convert.ToInt16((U)System.Enum.Parse(typeof(U), enumValue.ToString()));
		}

	}


	public enum ExpressionRelation
	{
		And,
		Or
	}

	public enum ExpressionValueRelation
	{
		Equal,
		NotEqual,
		GreaterThanOrEqual,
		GreaterThan,
		LessThan,
		LessThanOrEqual,
		Like
	}

	/// <summary>
	/// 多条件查询类
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class ExpressionCondition<T>
	{
		private ExpressionCondition()
		{

		}

		public static ExpressionCondition<T> GetInstance()
		{
			return new ExpressionCondition<T>();
		}

		private Expression conditionExpression { get; set; }
		private ParameterExpression parameter = Expression.Parameter(typeof(T));
		private ExpressionCondition<T> ComposeCondition(Expression<Func<T, object>> member, object value, ExpressionValueRelation valueRelation, ExpressionRelation expressionRelation)
		{
			if (value == null)
				return this;

			MemberExpression memberExpr = null;
			if (member.Body.NodeType == ExpressionType.Convert)
				memberExpr = ((UnaryExpression)member.Body).Operand as MemberExpression;
			else if (member.Body.NodeType == ExpressionType.MemberAccess)
				memberExpr = member.Body as MemberExpression;
			MemberExpression left = Expression.Property(parameter, memberExpr.Member.Name);
			ConstantExpression right = Expression.Constant(value,memberExpr.Type);
			
			Expression tempBinary = null;
			switch (valueRelation)
			{
				case ExpressionValueRelation.Equal:
					tempBinary = Expression.Equal(left, right);
					break;
				case ExpressionValueRelation.NotEqual:
					tempBinary = Expression.NotEqual(left, right);
					break;
				case ExpressionValueRelation.GreaterThan:
					tempBinary = Expression.GreaterThan(left, right);
					break;
				case ExpressionValueRelation.GreaterThanOrEqual:
					tempBinary = Expression.GreaterThanOrEqual(left, right);
					break;
				case ExpressionValueRelation.LessThan:
					tempBinary = Expression.LessThan(left, right);
					break;
				case ExpressionValueRelation.LessThanOrEqual:
					tempBinary = Expression.LessThanOrEqual(left, right);
					break;
				case ExpressionValueRelation.Like:
					var IsLikeMethod = typeof(NHibernateLinqExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).First(mi => mi.Name == "IsLike");
					right = value == null ? Expression.Constant("%%") : Expression.Constant(string.Format("%{0}%", value.ToString()));
					var callMethod = Expression.Call(IsLikeMethod, left, right);
					tempBinary = callMethod;
					break;
				default:
					break;
			}

			if (conditionExpression != null)
			{
				switch (expressionRelation)
				{
					case ExpressionRelation.And:
						conditionExpression = Expression.MakeBinary(ExpressionType.AndAlso, conditionExpression, tempBinary);
						break;
					case ExpressionRelation.Or:
						conditionExpression = Expression.MakeBinary(ExpressionType.OrElse, conditionExpression, tempBinary);
						break;
					default:
						break;
				}
			}
			else
				conditionExpression = tempBinary;
			return this;
		}

		/// <summary>
		/// And 条件
		/// </summary>
		/// <param name="member"></param>
		/// <param name="value"></param>
		/// <param name="valueRelation"></param>
		/// <returns></returns>
		public ExpressionCondition<T> And(Expression<Func<T, object>> member, object value, ExpressionValueRelation valueRelation)
		{
			return ComposeCondition(member, value, valueRelation, ExpressionRelation.And);
		}

		/// <summary>
		/// Or 条件
		/// </summary>
		/// <param name="member"></param>
		/// <param name="value"></param>
		/// <param name="valueRelation"></param>
		/// <returns></returns>
		public ExpressionCondition<T> Or(Expression<Func<T, object>> member, object value, ExpressionValueRelation valueRelation)
		{
			return ComposeCondition(member, value, valueRelation, ExpressionRelation.Or);
		}

		/// <summary>
		/// 查询表达式
		/// </summary>
		public Expression<Func<T, bool>> ConditionExpression
		{
			get
			{
				if (conditionExpression == null)
					return null;
				return Expression.Lambda<Func<T, bool>>(conditionExpression, parameter);
			}
		}
	}
}